登录token失效后,自动更新
- 在开发时总会遇到用户登录信息失效,需要重登操作,如是在用户操作时,需要重登,很影响用户体验
可参考的解决方法:
- 后端于用户操作时延长登录时效(存在弊端)。
- 后端取消登录时效。
- 前端进行自动重登。
这里主要讲解第 3 个方法,讲解示例 axios
参考文档:封装 Axios 封装(拦截器)
要点:
- 缓存 token,建议使用依赖库 js-cookie 自行封装,此处为了精简代码使用 localStorage。
- isUpdate 标识更新 Token 中,作用:1.防止重复更新。2.用于多并发请求时暂存后续请求队列的标识。
- response.config 是原请求的配置,config 内 已经带上了 baseUrl,因此重新请求时需要去掉,同时更新 token。
- 更新 token 后重新请求 token 失效时的请求。
示例
import axios from "axios";
import qs from 'qs';
const tokenName = "token";
// 从 localStorage 获取缓存的 token
const getToken = () => {
return window.localStorage.getItem(tokenName);
};
// 给实例添加一个 setToken 方法,用于登录后将最新 token 动态添加到 header,同时将 token 缓存
instance.setToken = (token) => {
instance.defaults.headers[tokenName] = token;
window.localStorage.setItem(tokenName, token);
};
const updateTokenFun = () => {
// instance是已创建的axios实例
return instance.post("更新登录信息的地址url");
};
// 重置 config 信息
const resetConfig = (config) => {
config.baseURL = '';
config.headers[tokenName] = token;
}
const baseURL = "请求地址";
// 创建一个axios实例
const instance = axios.create({
baseURL,
timeout: 500000 // 请求超时时间(毫秒)
headers: {
"Content-Type": "application/json",
token: getToken(),
},
});
// 更新状态标记
let isUpdate = false;
// 待请求队列
let requests = [];
// 响应请求的拦截器
instance.interceptors.response.use(
(response) => {
// 对回调数据进行处理
const { code } = response.data;
// 定义token 失效时的 code 值,需和后端沟通
if (code === 10086) {
const config = response.config;
// 更新用户信息
if (!isUpdate) {
isUpdate = true;
return updateTokenFun().then((res) => {
const { token } = res.data;
instance.setToken(token);
resetConfig(config)
// 用户信息已刷新,将更新中挂起的队列进行遍历请求
requests.forEach((cb) => cb(token));
// 清除Promise队列
requests = [];
// * 继续当前请求
return instance(config);
}).catch((res) => {
console.error("更新失败", res);
// 更新失败,重置页面至首页
window.location.href = "/";
}).finally(() => {
isUpdate = false;
});
} else {
// 用户信息更新中,通过Promise挂起后续请求,等待更新后遍历请求
return new Promise((resolve) => {
requests.push((token) => {
resetConfig(config)
resolve(instance(config));
});
});
}
}
return response;
}, (error) => {
// 处理请求回调错误
return Promise.reject(error);
});
export default instance;
Powered by Waline v2.15.8